{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Move existing user content to a new user\n",
    "This sample illustrates how to \"move\" a portal user's account to a new user account.  This is accomplished by creating a new user account, assigning ownership/membership of this new user to all the applicable groups, and then reassigning the old user's content to the new user connect while maintaining folder structure under 'My Contents'.\n",
    "\n",
    "For some customers, this is a useful utility when they have used one type of Identity store, e.g. Built-in Users, and then decided to switch to a different Identity provider, such as SAML or IWA.  In these situations, it is highly likely new userids will be created as new user accounts get created.  This Jupyter Notebook is an example of how to use the Python API to take a user's content and migrate it to a new userid while maintaining all group membership and content (including folders in My Content)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [],
   "source": [
    "from arcgis.gis import *\n",
    "from IPython.display import display"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create a connection to the portal.  In this case, we will exercise the verify_cert option to not validate the SSL certificate (True by default)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [],
   "source": [
    "gis = GIS(profile=\"your_online_profile\", verify_cert=False) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Establish variables for the current userid that is being transitioned and for the new userid to be created (e.g. a new Single Sign-on username)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [],
   "source": [
    "orig_userid = \"First_User\"\n",
    "new_userid = \"Second_User\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Validate that the original userid is valid and accessible."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div class=\"9item_container\" style=\"height: auto; overflow: hidden; border: 1px solid #cfcfcf; border-radius: 2px; background: #f6fafa; line-height: 1.21429em; padding: 10px;\">\n",
       "                    <div class=\"item_left\" style=\"width: 210px; float: left;\">\n",
       "                       <a href='https://pythonapi.playground.esri.com/portal/home/user.html?user=First_User' target='_blank'>\n",
       "                        <img src='' width='200' height='133' class=\"itemThumbnail\">\n",
       "                       </a>\n",
       "                    </div>\n",
       "\n",
       "                    <div class=\"item_right\" style=\"float: none; width: auto; overflow: hidden;\">\n",
       "                        <a href='https://pythonapi.playground.esri.com/portal/home/user.html?user=First_User' target='_blank'><b>First User</b>\n",
       "                        </a>\n",
       "                        <br/><br/><b>Bio</b>: Demonstrating application of various tools of ArcGIS Python API\n",
       "                        <br/><b>First Name</b>: First\n",
       "                        <br/><b>Last Name</b>: User\n",
       "                        <br/><b>Username</b>: First_User\n",
       "                        <br/><b>Joined</b>: July 05, 2017\n",
       "\n",
       "                    </div>\n",
       "                </div>\n",
       "                "
      ],
      "text/plain": [
       "<User username:First_User>"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "olduser = gis.users.get(orig_userid)\n",
    "olduser"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create a new userid, making sure to use `provider='enterprise'` if Web Tier Authentication is going to be used.  If moving user accounts from one userid to another, make sure that a proper password is used that meets security requirements."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    },
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "newuser = gis.users.create(username = new_userid,\n",
    "                            password = \"pwdNotUsed\",\n",
    "                            firstname = olduser.firstName,\n",
    "                            lastname = olduser.lastName,\n",
    "                            email = olduser.email,\n",
    "                            description = olduser.description,\n",
    "                            role = olduser.role,\n",
    "                            provider = 'enterprise',\n",
    "                            idp_username=None)   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once the new user has been successfully created, reassign group ownership and group membership from the old user to the new user."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [],
   "source": [
    "usergroups = olduser['groups']\n",
    "\n",
    "for group in usergroups:\n",
    "    grp = gis.groups.get(group['id'])\n",
    "    if (grp.owner == orig_userid):\n",
    "        grp.reassign_to(new_userid)\n",
    "    else:\n",
    "        grp.add_users(new_userid)\n",
    "        grp.remove_users(orig_userid)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once group ownership/membership has been successfully changed, reassign all the original user's content to the new user.  This happens in 2 passes.  First, reassign everything on the root folder of 'My Contents'.  Then, loop over each folder, create the same folder in the new user account, and reassign items in each folder to the new user in the correct folder."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Item does not exist or is inaccessible.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Item may have been already assigned to the user.\n"
     ]
    }
   ],
   "source": [
    "usercontent = olduser.items()\n",
    "\n",
    "folders = olduser.folders\n",
    "for item in usercontent:\n",
    "    try:\n",
    "        item.reassign_to(new_userid)\n",
    "    except Exception as e:\n",
    "        print(\"Item may have been already assigned to the user.\")\n",
    "\n",
    "for folder in folders:\n",
    "    gis.content.folders.create(folder['title'], new_userid)\n",
    "    folderitems = olduser.items(folder=folder['title'])\n",
    "    for item in folderitems:\n",
    "        item.reassign_to(new_userid, target_folder=folder['title'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "  "
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
